import { Node, Prefab, director, instantiate, isValid, RenderTexture, SpriteFrame, find, Camera, view, tween } from "cc";
import { UIComponent } from "../Base/UIComponent";
import { Singleton } from "../Common";
import { UIEnum } from "../Enum";
import ResourcesManager from "./ResourcesManager";

export class UIManager extends Singleton {

    static get Ins() {
        return super.GetInstance<UIManager>()
    }

    maskSpriteFrame: SpriteFrame = null
    UIMap: Map<UIEnum, UIComponent> = new Map()
    /**
     * 
     * @param type UI类型
     * @param data 数据 可选
     * @param parent 父节点 可选 默认canvas
     */
    async show(type: UIEnum, data?: any, parent?: Node) {
        await this.generateMaskSF()
        const UI = this.UIMap.get(type)
        if (!UI) {
            this.loadUI(type, data, parent)
        } else {
            if (!isValid(UI.node, true)) {
                this.deleteUI(type)
                this.loadUI(type, data, parent)
            } else {
                UI.show(data, parent)
            }
        }
    }

    private loadUI(type: UIEnum, data?: any, parent?: Node) {
        ResourcesManager.Ins.loadRes('UIPrefab/' + type, Prefab).then((p: Prefab) => {
            const node = instantiate(p)
            node.parent = parent || director.getScene().getChildByName('Canvas')
            const UICom = node.getComponent(type) as UIComponent
            UICom.type = type
            this.UIMap.set(type, UICom)
            UICom.show(data, parent)
        })
    }

    private deleteUI(type: UIEnum) {
        this.UIMap.delete(type)
    }

    /** 销毁所有UI */
    destroyAllUI() {
        for (const i in this.UIMap) {
            this.UIMap[i].node.destroy()
        }
        this.UIMap = new Map()
    }

    /** 生成mask用图片 */
    async generateMaskSF() {
        return new Promise((resolve) => {

            const camera = find('Canvas/Camera')
            const camera2 = instantiate(camera)
            camera2.destroyAllChildren()
            const tempCamera = camera2.getComponent(Camera)

            tempCamera.node.parent = camera.parent
            tempCamera.node.setPosition(camera.getPosition())
            const renderTex = new RenderTexture();
            const size = view.getVisibleSize()
            renderTex.reset({
                width: size.width,
                height: size.height,
            });
            tempCamera.targetTexture = renderTex;
            this.maskSpriteFrame = new SpriteFrame()
            this.maskSpriteFrame.texture = renderTex

            tween(tempCamera)
                .delay(0)
                .call(() => {
                    tempCamera.targetTexture = null;
                    tempCamera.destroy()
                    resolve(null)
                })
                .start()
        })

    }

    getMaskSpriteFrame() {
        const camera = find('Canvas/Camera').getComponent(Camera)
        return this.maskSpriteFrame
    }
}